package javaLabs.lab1.ListQueue;

import junit.framework.TestCase;
import org.junit.*;
import org.junit.rules.ExpectedException;

import java.util.*;

public class ListQueueTest extends TestCase {

    private ListQueue queue = null;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        queue = new ListQueue();
    }

    @After
    public void tearDown() throws Exception {
        queue = null;
    }

    public void testIterator() throws Exception {

        Integer[] numbers = {5, 10, 15, 20, 25};
        Collections.addAll(queue, numbers);

        Iterator<Integer> it = queue.iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }

        assertEquals("Queue isn't empty!", true, queue.isEmpty());

        Collections.addAll(queue, numbers);
        it = queue.iterator();

        Integer value = 0;

        while (it.hasNext() && (value = it.next()) != 15) {
            it.remove();
        }

        assertEquals("Incorrect iterator's remove!", true, Arrays.equals(queue.toArray(), new Integer[]{15, 20, 25}));
    }

    public void testSize() throws Exception {
        assertEquals("Queue must be empty!", 0, queue.size());
    }

    public void testOffer() throws Exception {
        for (int i = 0; i < 100; ++i) {
            queue.offer(i);
            assertEquals("Queue's size isn't valid!", queue.size(), i + 1);
        }
    }

    public void testAdd() throws Exception {
        for (int i = 0; i < 100; ++i) {
            queue.add(i);
            assertEquals("Queue's size isn't valid!", queue.size(), i + 1);
        }
    }

    public void testRemove() throws Exception {
        Integer[] numbers = {5, 10, 15, 20, 25};

        Collections.addAll(queue, numbers);

        queue.remove(5);
        assertEquals("Incorrect remove!", true, Arrays.equals(queue.toArray(), new Integer[]{10, 15, 20, 25}));

        queue.offer(42);
        assertEquals("Incorrect offer after removing!", true, Arrays.equals(queue.toArray(), new Integer[]{10, 15, 20, 25, 42}));

        queue.remove(20);
        assertEquals("Incorrect remove!", true, Arrays.equals(queue.toArray(), new Integer[]{10, 15, 25, 42}));

        queue.remove();
        assertEquals("Incorrect remove!", true, Arrays.equals(queue.toArray(), new Integer[]{15, 25, 42}));
    }

    public void testPoll() throws Exception {
        Integer[] numbers = {5, 10, 15, 20, 25};

        Collections.addAll(queue, numbers);

        queue.poll();
        assertEquals("Incorrect poll!", true, Arrays.equals(queue.toArray(), new Integer[]{10, 15, 20, 25}));

        queue.poll();
        assertEquals("Incorrect poll!", true, Arrays.equals(queue.toArray(), new Integer[]{15, 20, 25}));

        queue.add(42);
        Integer headValue = queue.poll();
        assertEquals("Queue's head is incorrect", 15, headValue.intValue());
        assertEquals("Incorrect poll!", true, Arrays.equals(queue.toArray(), new Integer[]{20, 25, 42}));

        queue.clear();
        headValue = queue.poll();
        assertEquals("Queue's head isn't null", null, headValue);
    }

    /*

    Для JUnit4, однако текущий тест на версии JUnit3.

    @Rule public ExpectedException testElementNoSuchElementException = ExpectedException.none();

    // element кидает NoSuchElementException в случае пустой очереди - проверим это
    public void testElementQueueIsEmpty() throws NoSuchElementException {
        testElementNoSuchElementException.expect(NoSuchElementException.class);
        testElementNoSuchElementException.expectMessage("test");

        queue.element();
    }
    */

    public void testPeek() throws Exception {
        Integer[] numbers = {5, 10, 15, 20, 25};

        Collections.addAll(queue, numbers);

        assertEquals("Peek is incorrect!", 5, queue.peek().intValue());

        queue.clear();

        assertEquals("Peek is incorrect!", null, queue.peek());
    }

    public void testIsEmpty() throws Exception {
        assertEquals("Queue must be empty!", true, queue.isEmpty());

        queue.offer(5);

        assertEquals("Queue must not be empty!", false, queue.isEmpty());

        queue.poll();

        assertEquals("Queue must be empty!", true, queue.isEmpty());
    }

    public void testContains() throws Exception {
        assertEquals("This element isn't in queue!", false, queue.contains(5));

        Integer[] numbers = {5, 10, 15, 20, 25};

        Collections.addAll(queue, numbers);

        assertEquals("This element must be in queue!", true, queue.contains(5));
        assertEquals("This element must be in queue!", true, queue.contains(25));
        assertEquals("This element must be in queue!", true, queue.contains(15));

        assertEquals("This element isn't in queue!", false, queue.contains(0));
    }

    public void testToArray() throws Exception {
        Object[] queueArray = queue.toArray();
        assertEquals("Array must be empty!", 0, queueArray.length);

        int size = 6;

        Integer[] numericArray = new Integer[size];
        for (int i = 0; i < size; ++i) {
            queue.offer(i);
            numericArray[i] = i;
        }

        queueArray = queue.toArray();

        assertEquals("Arrays is not equal!", true, Arrays.equals(queueArray, numericArray));
    }


    public void testContainsAll() throws Exception {

        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        Integer[] numbers = {5, 10, 15, 20, 25};

        for (Integer integer : numbers) {
            queue.offer(integer);
            if (integer % 2 != 0) {
                arrayList.add(integer);
            }
        }

        assertEquals("All of this elements are in queue!", true, queue.containsAll(arrayList));

        arrayList.add(0);

        assertEquals("0 isn't in queue!", false, queue.containsAll(arrayList));
    }

    public void testAddAll() throws Exception {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();

        Integer[] numbers = {5, 10, 15, 20, 25};

        Collections.addAll(arrayList, numbers);

        queue.addAll(arrayList);

        assertEquals("Queue != initArray", true, Arrays.equals(queue.toArray(), numbers));
    }

    public void testRemoveAll() throws Exception {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();

        Integer[] numbers = {5, 10, 15, 20, 25};

        for (Integer integer : numbers) {
            queue.offer(integer);
            if (integer % 2 != 0) {
                arrayList.add(integer);
            }
        }

        queue.removeAll(arrayList);

        assertEquals("Incorrect removeAll!", true, Arrays.equals(queue.toArray(), new Integer[]{10, 20}));
    }

    public void testRetainAll() throws Exception {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();

        Integer[] numbers = {5, 10, 15, 20, 25};

        for (Integer integer : numbers) {
            queue.offer(integer);
            if (integer % 2 != 0) {
                arrayList.add(integer);
            }
        }

        queue.retainAll(arrayList);

        assertEquals("Incorrect retainAll!", true, Arrays.equals(queue.toArray(), new Integer[]{5, 15, 25}));
    }

    public void testClear() throws Exception {
        queue.clear();
        assertEquals("Size after clear != 0", 0, queue.size());

        Integer[] numbers = {5, 10, 15, 20, 25};

        for (Integer integer : numbers) {
            queue.offer(integer);
        }

        queue.clear();
        assertEquals("Size after clear != 0", 0, queue.size());

    }

    public void testToString() throws Exception {
        assertEquals("Empty queue's presentation is not valid!", "[]", queue.toString());
        for (int i = 0; i < 6; ++i) {
            queue.offer(i);
        }
        assertEquals("Queue's presentation is not valid!", "[0, 1, 2, 3, 4, 5]", queue.toString());
    }
}
